package com.example.rbacmanage.service.system.impl;

import com.alibaba.druid.util.StringUtils;
import com.example.rbacmanage.annotation.PermissionRange;
import com.example.rbacmanage.common.Constant;
import com.example.rbacmanage.entity.system.UserLog;
import com.example.rbacmanage.entity.system.UserRole;
import com.example.rbacmanage.mapper.system.UserLogMapper;
import com.example.rbacmanage.mapper.system.UserMapper;
import com.example.rbacmanage.entity.system.User;
import com.example.rbacmanage.mapper.system.UserRoleMapper;
import com.example.rbacmanage.service.system.UserService;
import com.example.rbacmanage.util.JwtTokenUtil;
import com.example.rbacmanage.vo.MyUserDetails;
import com.example.rbacmanage.vo.UserLoginReq;
import com.example.rbacmanage.vo.UserRegisterReq;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private UserLogMapper userLogMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Override
    public void save(User o) {
        if(!StringUtils.isEmpty(o.getPassword())){
            String passworddecode = passwordEncoder.encode(o.getPassword());
            o.setPassword(passworddecode);
        }
        userMapper.insert(o);

        if (!CollectionUtils.isEmpty(o.getRoleIds())){
            for (Long roleId:o.getRoleIds()){
                UserRole userRole = new UserRole();
                userRole.setRoleId(roleId);
                userRole.setUserId(o.getId());
                userRoleMapper.insert(userRole);
            }
        }
    }

    @Override
    public void remove(Long[] ids) {
        for(Long id:ids){
            userMapper.del(id);
            //同事删除用户角色关系表
            userRoleMapper.deleteByUserId(id);
        }
    }

    @Override
    public void update(User o) {
        if(!StringUtils.isEmpty(o.getPassword())){
            String passworddecode = passwordEncoder.encode(o.getPassword());
            o.setPassword(passworddecode);
        }
        userMapper.update(o);

        UserRole userRole = new UserRole();
        userRole.setUserId(o.getId());
        List<UserRole> userRoles = userRoleMapper.list(userRole);
        List<Long> oldUserIds = userRoles.stream().map(UserRole::getRoleId).collect(Collectors.toList());
        //判断原本的角色在新角色是否存在，不存在则删除
        for (UserRole userRole1:userRoles){
            boolean exist = false;
            if (!CollectionUtils.isEmpty(o.getRoleIds()) && o.getRoleIds().contains(userRole1.getRoleId())){
                exist=true;
            }
            if (!exist){
                userRoleMapper.del(userRole1.getId());
            }
        }
        //判断新角色在原本角色是否存在，不存在，则新增
        if (!CollectionUtils.isEmpty(o.getRoleIds())){
            for (Long roleId:o.getRoleIds()){
                boolean exist = false;
                if (oldUserIds.contains(roleId)){
                    exist=true;
                }
                if (!exist){
                    UserRole userRole1 = new UserRole();
                    userRole1.setRoleId(roleId);
                    userRole1.setUserId(o.getId());
                    userRoleMapper.insert(userRole1);
                }
            }
        }
    }

    @Override
    public List<User> getAll(User user) {
        return userMapper.list(user);
    }

    @Override
    @PermissionRange(deptAlias = "d",userAlias = "u")
    public PageInfo<User> getPage(User o) {
        PageHelper.startPage(o.getPage(), o.getLimit());
        return new PageInfo<>(userMapper.list(o));
    }

    @Override
    public User getById(Long id) {
        User user = userMapper.queryOneById(id);
        if (user == null){
            return user;
        }
        UserRole userRole = new UserRole();
        userRole.setUserId(user.getId());
        List<UserRole> userRoles = userRoleMapper.list(userRole);
        List<Long> roleIds = userRoles.stream().map(UserRole::getRoleId).collect(Collectors.toList());
        user.setRoleIds(roleIds);
        return user;
    }

    @Override
    public Integer getCount(User user) {
        return userMapper.count(user);
    }

    @Override
    public String login(UserLoginReq req){
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(req.getUsername(), req.getPassword());
        Authentication authentication = null;
        try{
            authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }catch (BadCredentialsException e ){
            e.printStackTrace();
           System.out.println("用户名或密码错误");
           return null;
        }

        if(authentication == null){
            return null;
        }

        Object principal = authentication.getPrincipal();
        MyUserDetails userDetails = (MyUserDetails) principal;
        System.out.println(userDetails.toString());
        String token = JwtTokenUtil.generateToken(userDetails.getUsername());
        Date expireDate=JwtTokenUtil.getExpiredDateFromToken(token);
        redisTemplate.opsForValue().set(Constant.systemLoginUserToken +userDetails.getUsername(),token,expireDate.getTime(), TimeUnit.MILLISECONDS);
        UserLog userLog = new UserLog();
        userLog.setIp(null);
        userLog.setOperType("登录");
        userLog.setOperTime(new Date());
        userLog.setOperName(userDetails.getUsername());
        userLog.setCreateBy(userDetails.getUsername());
        userLog.setCreateTime(new Date());
        userLogMapper.insert(userLog);
        return token;
    }

    @Override
    public String register(UserRegisterReq req) {
        String passworddecode = passwordEncoder.encode(req.getPassword());
        User user = new User();
        user.setUserName(req.getUsername());
        user.setPassword(passworddecode);
        user.setEmail(req.getEmail());
        user.setPhone(req.getPhone());
        user.setCreateTime(new Date());
        user.setCreateBy(req.getUsername());
        user.setUpdateTime(new Date());
        user.setUpdateBy(req.getUsername());
        userMapper.insert(user);
        return "注册成功";
    }

    @Override
    public MyUserDetails getLoginInfo() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if(authentication != null){
            Object principal = authentication.getPrincipal();
            return (MyUserDetails) principal;
        }
        return null;
    }

    @PermissionRange(deptAlias = "d")
    @Override
    public PageInfo<User> getAssignUserPage(User user) {
        PageHelper.startPage(user.getPage(), user.getLimit());
        return new PageInfo<>(userMapper.selectListByRoleId(user));
    }

    @PermissionRange(deptAlias = "d")
    @Override
    public PageInfo<User> getUnAssignUserPage(User user) {
        PageHelper.startPage(user.getPage(), user.getLimit());
        return new PageInfo<>(userMapper.selectListByNotRoleId(user));
    }
}
